using System.IO;
using System.Text;
using OracleInternal.Json.Common;

namespace OracleInternal.Json.Binary
{
	internal sealed class OsonBuffer
	{
		internal ByteBuffer m_buffer;

		internal char[] m_charBuffer;

		internal OsonBuffer(ByteBuffer buffer)
		{
			m_buffer = buffer;
		}

		internal OsonBuffer(MemoryStream buffer)
		{
			m_buffer = ByteBuffer.Wrap(buffer.ToArray());
		}

		internal int GetInt()
		{
			return m_buffer.GetInt();
		}

		internal ByteBuffer Buffer()
		{
			return m_buffer;
		}

		internal int Position()
		{
			return m_buffer.Position();
		}

		internal void Position(int pos)
		{
			m_buffer.Position(pos);
		}

		internal int GetUB1()
		{
			return 0xFF & m_buffer.Get();
		}

		internal int GetUB1(int i)
		{
			return 0xFF & m_buffer.Get(i);
		}

		internal int GetUB2()
		{
			return 0xFFFF & m_buffer.GetShort();
		}

		internal int GetUB2(int i)
		{
			return 0xFFFF & m_buffer.GetShort(i);
		}

		internal char[] ReadString(int len, out int charArrLen)
		{
			byte[] array = m_buffer.Array();
			charArrLen = len;
			if (m_charBuffer == null || m_charBuffer.Length < len)
			{
				m_charBuffer = new char[len];
			}
			int num = m_buffer.Position();
			for (int i = 0; i < len; i++)
			{
				byte b = array[i + num];
				if ((sbyte)b < 0)
				{
					charArrLen = Encoding.UTF8.GetChars(array, num, len, m_charBuffer, 0);
					m_buffer.Position(num + len);
					return m_charBuffer;
				}
				m_charBuffer[i] = (char)b;
			}
			m_buffer.Position(num + len);
			return m_charBuffer;
		}

		internal int GetUB4int()
		{
			int @int = m_buffer.GetInt();
			if (@int < 0)
			{
				throw OracleJsonExceptions.OVERFLOW.Create(null, @int);
			}
			return @int;
		}

		internal int GetUB4int(int i)
		{
			int @int = m_buffer.GetInt(i);
			if (@int < 0)
			{
				throw OracleJsonExceptions.OVERFLOW.Create(null, @int);
			}
			return @int;
		}

		internal void Get(byte[] bytes)
		{
			m_buffer.Get(bytes);
		}

		internal double ReadDtyDouble()
		{
			byte[] array = new byte[8];
			m_buffer.Get(array);
			return OsonPrimitiveConversions.CanonicalFormatBytesToDouble(array);
		}

		internal float ReadDtyFloat()
		{
			byte[] array = new byte[4];
			m_buffer.Get(array);
			return OsonPrimitiveConversions.CanonicalFormatBytesToFloat(array);
		}

		internal int BinarySearchUb1(int fromPos, int count, int test)
		{
			int num = 0;
			int num2 = count - 1;
			byte[] array = m_buffer.Array();
			while (num <= num2)
			{
				int num3 = num + num2 >> 1;
				int num4 = array[fromPos + num3] & 0xFF;
				if (num4 < test)
				{
					num = num3 + 1;
					continue;
				}
				if (num4 > test)
				{
					num2 = num3 - 1;
					continue;
				}
				return num3;
			}
			return -1;
		}

		internal int BinarySearchUb2(int fromPos, int count, int test)
		{
			int num = 0;
			int num2 = count - 1;
			while (num <= num2)
			{
				int num3 = num + num2 >> 1;
				int uB = GetUB2(fromPos + num3 * 2);
				if (uB < test)
				{
					num = num3 + 1;
					continue;
				}
				if (uB > test)
				{
					num2 = num3 - 1;
					continue;
				}
				return num3;
			}
			return -1;
		}

		internal int BinarySearchUb4(int fromPos, int count, int test)
		{
			int num = 0;
			int num2 = count - 1;
			while (num <= num2)
			{
				int num3 = num + num2 >> 1;
				int uB4int = GetUB4int(fromPos + num3 * 4);
				if (uB4int < test)
				{
					num = num3 + 1;
					continue;
				}
				if (uB4int > test)
				{
					num2 = num3 - 1;
					continue;
				}
				return num3;
			}
			return -1;
		}

		internal int LinearSearchUb1(int fromPos, int count, int test)
		{
			for (int i = fromPos; i < fromPos + count; i++)
			{
				if (GetUB1(i) == test)
				{
					return i - fromPos;
				}
			}
			return -1;
		}

		internal int LinearSearchUb2(int fromPos, int count, int test)
		{
			int num = fromPos + count * 2;
			for (int i = fromPos; i < num; i += 2)
			{
				if (GetUB2(i) == test)
				{
					return (i - fromPos) / 2;
				}
			}
			return -1;
		}

		internal int LinearSearchUb4(int fromPos, int count, int test)
		{
			int num = fromPos + count * 4;
			for (int i = fromPos; i < num; i += 4)
			{
				if (GetUB4int(i) == test)
				{
					return (i - fromPos) / 4;
				}
			}
			return -1;
		}
	}
}
